<template>
  <div>
    <article-templates :data="articleData">
      <template #article>
        <esign-com />

        <title-card title="使用"></title-card>
        <pre-code :code="code1" language="xml" />
        <pre-code style="margin-top: 20px;" :code="code2" language="JavaScript" />
      </template>
    </article-templates>
  </div>
</template>

<script setup name="Esign">
import ArticleTemplates from '@/components/ArticleTemplates/index.vue';
import TitleCard from "@/components/TitleCard/index.vue"
import EsignCom from "./EsignCom/index.vue"
import { postArticleDetail } from '@/api/home.js';
import { onMounted, ref, toRefs, reactive } from 'vue';

const data = reactive({
  articleData: {},
});
const { articleData } = toRefs(data);

const code1 = ref(`<canvas 
  ref="canvas"
  @mousedown="mouseDown" 
  @mousemove="mouseMove" 
  @mouseup="mouseUp"
  @touchstart="touchStart" 
  @touchmove="touchMove" 
  @touchend="touchEnd"
></canvas>`);
const code2 = ref(`import { onMounted, ref, toRefs, computed, watch } from "vue";

const emit = defineEmits([]);
const prop = defineProps({
  width: {
    type: Number,
    default: 800
  },
  height: {
    type: Number,
    default: 300
  },
  lineWidth: {
    type: Number,
    default: 4
  },
  lineColor: {
    type: String,
    default: '#000000'
  },
  bgColor: {
    type: String,
    default: ''
  },
  isCrop: {
    type: Boolean,
    default: false
  },
  isClearBgColor: {
    type: Boolean,
    default: true
  },
  format: {
    type: String,
    default: 'image/png'
  },
  quality: {
    type: Number,
    default: 1
  }
});
const { width, height, lineWidth, lineColor, bgColor, isCrop, isClearBgColor, format, quality } = toRefs(prop);
const canvas = ref(null);
const hasDrew = ref(false);
const resultImg = ref('');
const points = ref([]);
const canvasTxt = ref(null);
const startX = ref(0);
const startY = ref(0);
const isDrawing = ref(false);
const sratio = ref(1);

const ratio = computed(()=>height/width);
const stageInfo = computed(()=>canvas.value.getBoundingClientRect());
const myBg = computed(()=>bgColor.value ? bgColor.value : 'rgba(255, 255, 255, 0)');
watch(()=>myBg.value,(newVal)=>{
  canvas.value.style.background = newVal
},{
  deep: true
})

const beforeMount = () => {
  window.addEventListener('resize', $_resizeHandler);
}
const beforeDestroy = () => {
  window.removeEventListener('resize', $_resizeHandler)
}

const $_resizeHandler = () => {
  canvas.value.style.width = width.value + "px"
  const realw = parseFloat(window.getComputedStyle(canvas.value).width)
  canvas.value.style.height = ratio.value * realw + "px";
  canvasTxt.value = canvas.value.getContext('2d')
  canvasTxt.value.scale(1 * sratio.value, 1 * sratio)
  sratio.value = realw / width.value
  canvasTxt.value.scale(1 / sratio.value, 1 / sratio.value)
};

// pc
const mouseDown = (e) => {
  e = e || event
  e.preventDefault()
  isDrawing.value = true
  hasDrew.value = true
  let obj = {
    x: e.offsetX,
    y: e.offsetY
  }
  drawStart(obj)
};
const mouseMove = (e) => {
  e = e || event
  e.preventDefault()
  if (isDrawing.value) {
    let obj = {
      x: e.offsetX,
      y: e.offsetY
    }
    drawMove(obj)
  }
};
const mouseUp = (e) => {
  e = e || event
  e.preventDefault()
  let obj = {
    x: e.offsetX,
    y: e.offsetY
  }
  drawEnd(obj)
  isDrawing.value = false
};
// mobile
const touchStart = (e) => {
  e = e || event
  e.preventDefault()
  hasDrew.value = true
  if (e.touches.length === 1) {
    let obj = {
      x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
      y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
    }
    drawStart(obj)
  }
};
const touchMove = (e) => {
  e = e || event
  e.preventDefault()
  if (e.touches.length === 1) {
    let obj = {
      x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
      y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
    }
    drawMove(obj)
  }
};
const touchEnd = (e) => {
  e = e || event
  e.preventDefault()
  if (e.touches.length === 1) {
    let obj = {
      x: e.targetTouches[0].clientX - canvas.value.getBoundingClientRect().left,
      y: e.targetTouches[0].clientY - canvas.value.getBoundingClientRect().top
    }
    drawEnd(obj)
  }
}
// 绘制
const drawStart = (obj) => {
  startX.value = obj.x
  startY.value = obj.y
  canvasTxt.value.beginPath()
  canvasTxt.value.moveTo(startX.value, startY.value)
  canvasTxt.value.lineTo(obj.x, obj.y)
  canvasTxt.value.lineCap = 'round'
  canvasTxt.value.lineJoin = 'round'
  canvasTxt.value.lineWidth = lineWidth.value * sratio.value
  canvasTxt.value.stroke()
  canvasTxt.value.closePath()
  points.value.push(obj)
};
const drawMove = (obj) => {
  canvasTxt.value.beginPath()
  canvasTxt.value.moveTo(startX.value, startY.value)
  canvasTxt.value.lineTo(obj.x, obj.y)
  canvasTxt.value.strokeStyle = lineColor.value
  canvasTxt.value.lineWidth = lineWidth.value * sratio.value
  canvasTxt.value.lineCap = 'round'
  canvasTxt.value.lineJoin = 'round'
  canvasTxt.value.stroke()
  canvasTxt.value.closePath()
  startY.value = obj.y
  startX.value = obj.x
  points.value.push(obj)
};
const drawEnd = (obj) => {
  canvasTxt.value.beginPath()
  canvasTxt.value.moveTo(startX.value, startY.value)
  canvasTxt.value.lineTo(obj.x, obj.y)
  canvasTxt.value.lineCap = 'round'
  canvasTxt.value.lineJoin = 'round'
  canvasTxt.value.stroke()
  canvasTxt.value.closePath()
  points.value.push(obj)
  points.value.push({x: -1, y: -1})
};
// 操作
const generate = (options) => {
  let imgFormat = options && options.format ? options.format: format.value
  let imgQuality = options && options.quality ? options.quality: quality.value
  console.log(imgFormat);
  const pm =  new Promise((resolve, reject) => {
    if (!hasDrew.value) {
      reject('Warning: Not Signned!')
      return
    }
    var resImgData = canvasTxt.value.getImageData(0, 0, canvas.value.width, canvas.value.height)
    canvasTxt.value.globalCompositeOperation = "destination-over"
    canvasTxt.value.fillStyle = myBg.value
    canvasTxt.value.fillRect(0,0,canvas.value.width ,canvas.value.height)
    resultImg.value = canvas.value.toDataURL(imgFormat, imgQuality)
    var resultImgData = resultImg.value
    canvasTxt.value.clearRect(0, 0, canvas.value.width ,canvas.value.height)
    canvasTxt.value.putImageData(resImgData, 0, 0)
    canvasTxt.value.globalCompositeOperation = "source-over"
    if (isCrop.value) {
      const crop_area = getCropArea(resImgData.data)
      var crop_canvas = document.createElement('canvas')
      const crop_ctx = crop_canvas.getContext('2d')
      crop_canvas.width = crop_area[2] - crop_area[0]
      crop_canvas.height = crop_area[3] - crop_area[1]
      const crop_imgData = canvasTxt.value.getImageData(...crop_area)
      crop_ctx.globalCompositeOperation = "destination-over"
      crop_ctx.putImageData(crop_imgData, 0, 0)
      crop_ctx.fillStyle = myBg.value
      crop_ctx.fillRect(0, 0, crop_canvas.width , crop_canvas.height)
      resultImgData = crop_canvas.toDataURL(imgFormat, imgQuality)
      crop_canvas = null
    }
    resolve(resultImgData)
  })
  return pm
};
const reset = () => {
  canvasTxt.value.clearRect(
    0,
    0,
    canvas.value.width,
    canvas.value.height
  )
  if (isClearBgColor.value) {
    emit('update:bgColor', '')
    canvas.value.style.background = 'rgba(255, 255, 255, 0)'
  }
  points.value = []
  hasDrew.value = false
  resultImg.value = ''
};
const getCropArea = (imgData) => {
  var topX = canvas.value.width; var btmX = 0; var topY = canvas.value.height; var btnY = 0
  for (var i = 0; i < canvas.value.width; i++) {
    for (var j = 0; j < canvas.value.height; j++) {
      var pos = (i + canvas.value.width * j) * 4
      if (imgData[pos] > 0 || imgData[pos + 1] > 0 || imgData[pos + 2] || imgData[pos + 3] > 0) {
        btnY = Math.max(j, btnY)
        btmX = Math.max(i, btmX)
        topY = Math.min(j, topY)
        topX = Math.min(i, topX)
      }
    }
  }
  topX++
  btmX++
  topY++
  btnY++
  const data = [topX, topY, btmX, btnY]
  return data
}

onMounted(() => {
  canvas.value.height = height.value
  canvas.value.width = width.value
  canvas.value.style.background = myBg.value
  console.log(myBg.value);
  $_resizeHandler()
  // 在画板以外松开鼠标后冻结画笔
  document.onmouseup = () => {
    isDrawing.value = false
  }
})
defineExpose({ generate, reset });`)

const getTitle = () => {
  postArticleDetail({
    route: 'Esign',
  }).then((res) => {
    articleData.value = res.data;
  });
};
onMounted(() => {
  getTitle();
});
</script>